package com.cyy.algovis

import javafx.animation.AnimationTimer
import javafx.collections.FXCollections
import javafx.scene.paint.Color
import javafx.scene.shape.Rectangle
import tornadofx.*
import java.lang.Thread.sleep


class 选择排序V : View("learn 选择排序") {
    //    每个矩形宽度
    val w = 10.0
    //    100个矩形容器
    val rec = FXCollections.observableArrayList<Rectangle>()
    //    动画计时器
    val aniTimer =AniTimer()
    val result = stringProperty()
    val swapNum = stringProperty()
    val N = 100
    val randomBound = 400
    val data0 = SelectionSortData(N, randomBound)
    val delay0 = 1L
    override val root = borderpane {
        top = vbox(5) {
            result.value = "result:${data0.numbers.toString()}"

            label(result) {
                isWrapText = true
            }
            label(swapNum)
            hbox(5) {
                button("run").action {
                    //                    aniTimer.start()

                    run {
                        aniTimer.start()
                    }
                }
                button("stop").action {
                    aniTimer.stop()
                }
            }
        }
        center = group {
            (1..N).forEach {
                val r = rectangle(w * it, 200.0, w - 2, data0.numbers[N - it]) {
                    fill = Color.GRAY
                }
                rec.add(r)
            }
            rotate = 180.0
        }
        prefHeight = 800.0
        prefWidth = 1000.0
    }

    fun paint() {
        setData(0, -1, -1)
        for (i in data0.numbers.indices) {
            var minIndex = i
            rec[minIndex].fill = Color.INDIGO

            setData(i, -1, minIndex)
            var j = i + 1
            if (j < data0.N()) {
                (j..data0.N()).map {
                    setData(i, j, minIndex)
                    if (data0.get(j) > data0.get(minIndex)) {
                        rec[j].fill = Color.LIGHTBLUE
                        rec[minIndex].fill = Color.LIGHTBLUE

                        swapNum.value =
                                "当前比较的数：j:${j}:${data0.get(j)} -- ${data0.orderedIndex} -- ${j}:${data0.get(j)}--${minIndex}:${data0.get(
                                        minIndex
                                )}"
                        minIndex = j
                        rec[minIndex].fill = Color.INDIGO
                        setData(i, j, minIndex)
                    }
                }
            }

            data0.swap(i, minIndex)
            setData(i+1, -1, -1)
            rec[i].height=data0.numbers[i].toDouble()
            rec[minIndex].height=data0.numbers[minIndex].toDouble()
            sleep(delay0)
            result.value = "result:${data0.numbers.reversed()}"
        }
        setData(data0.N(), -1, -1)
    }

    fun setData(orderedIndex: Int, currentCompareIndex: Int, currentMinIndex: Int) {
        data0.orderedIndex = orderedIndex
        data0.currentCompareIndex = currentCompareIndex
        data0.currentMinIndex = currentMinIndex
//        if(orderedIndex in (0..N-1)) {
//            (orderedIndex..N-1).map{
//                rec[it].fill = Color.RED
//            }
//        }
//        if(currentCompareIndex in (0..N-1)) {
//            rec[currentCompareIndex].fill = Color.LIGHTBLUE
//        }
//        if(currentMinIndex in (0..N-1)) {
//            rec[currentMinIndex].fill = Color.INDIGO
//        }

//        if (i == data0.currentCompareIndex) rec[i].fill = Color.LIGHTBLUE
//        if (i == data0.currentMinIndex) rec[i].fill = Color.INDIGO
    }

    // 此方法可以停止动画
    inner class AniTimer: AnimationTimer() {
        var lastTime = 0L
        override fun handle(now: Long) {
            if ((now - lastTime) > 10000000) {
                lastTime = now
            } else {
                return
            }
            paint()
        }
    }
}

class SelectionSortData {
    val numbers = ArrayList<Int>()
    //    [0..orderedIndex)是有序的
    var orderedIndex = -1
    //    当前找到的最小元素的索引
    var currentMinIndex = -1
    //    当前正在比较的元素的索引
    var currentCompareIndex = -1

    constructor(N: Int, randomBound: Int) {
        (1..N).map { numbers.add((1..randomBound).random()) }
    }

    fun N() = numbers.size
    fun get(i: Int) = numbers[i]
    fun swap(i: Int, j: Int) {
        val t = numbers[i]
        numbers[i] = numbers[j]
        numbers[j] = t
    }
}